package frontend.core;

import backend.model.base.DBModel;
import backend.model.admin.Employee;
import backend.model.other.User;
import backend.service.base.DBModelService;
import backend.service.other.UserService;
import frontend.pages.error.InternalErrorPage;
import frontend.pages.login.LoginPage;
import frontend.pages.worklog.daily.DailyWorkLogPage;
import org.apache.wicket.Page;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.parser.filter.WicketTagIdentifier;
import org.apache.wicket.markup.resolver.FragmentResolver;
import org.apache.wicket.settings.IExceptionSettings;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.wicketstuff.annotation.scan.AnnotatedMountScanner;
import shared.other.DBModelToServiceNameMap;

public class TimeTrackingWebApplication extends AuthenticatedWebApplication implements ApplicationContextAware {
	
	static {
		WicketTagIdentifier.registerWellKnownTagName("component");
	}

	private static ApplicationContext context;

	@Override
	public Class<? extends Page> getHomePage() {
		return DailyWorkLogPage.class;
	}

	@Override
	protected void init() {
		super.init();
		addSpringInitializer();
		getPageSettings().addComponentResolver(new FragmentResolver());
        mountPages();
        setInternalErrorPage();

	}

    private void setInternalErrorPage() {
        getApplicationSettings().setInternalErrorPage(InternalErrorPage.class);
        getExceptionSettings().setUnexpectedExceptionDisplay(IExceptionSettings.SHOW_INTERNAL_ERROR_PAGE);
    }

    private void mountPages() {
        new AnnotatedMountScanner().scanPackage("frontend.pages").mount(this);
    }

    protected void addSpringInitializer() {
		getComponentInstantiationListeners().add(new SpringComponentInjector(this));
	}

	@Override
	protected Class<? extends WebPage> getSignInPageClass() {
		return LoginPage.class;
	}

	@Override
	protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() {
		return TimeTrackingWebSession.class;
	}

	@Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		context = applicationContext;
	}

	public static <T extends DBModelService> T getService(Class<T> serviceClass) {
		return context.getBean(serviceClass);
	}

	public static DBModelService getServiceByDBModel(Class<? extends DBModel> dbModelClass) {
		Class serviceClass = DBModelToServiceNameMap.getServiceByDBModel(dbModelClass);
		return getService(serviceClass);
	}

    public static <T> T getBean(Class<T> clazz) {
        return context.getBean(clazz);
    }

    public static Employee getLoggedInEmployee() {
        User loggedInUser = getLoggedInUser();
        return loggedInUser.getEmployee();
    }

    public static User getLoggedInUser() {
        String loggedInUsername = (String) TimeTrackingWebSession.get().getAttribute(TimeTrackingWebSession.LOGIN_USERNAME_ATTR);
        return TimeTrackingWebApplication.getService(UserService.class).findUserByUsername(loggedInUsername);
    }
}